import { Injectable, InternalServerErrorException, NotFoundException } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { DataSource, In, Repository } from 'typeorm'
import { BotClientService } from '@boticord/bot-client'
import { cloudflareChallenges, ErrorCodes } from '@boticord/consts'
import { User } from '@boticord/users-client'
import { Bot, Server } from '@boticord/resources-client'

@Injectable()
export class ValidationUtil {
  constructor(
    private readonly bot: BotClientService,
    @InjectRepository(User) private readonly users: Repository<User>,
    private readonly source: DataSource,
  ) {}

  /** this will check if invite that was sent is invalid (or points to another server) */
  async checkInviteCode(id: string, inviteCode: string): Promise<boolean> {
    return !!this.bot // TODO: discordoo developers hello there ??
  }

  async resolveUsers(ids: string[]) {
    const users = await this.users.find({ where: { id: In(ids) } })

    if (users.length !== ids.length) {
      throw new NotFoundException({ code: ErrorCodes.UnknownUser })
    }

    return users
  }

  // check if short link is not taken
  async checkShortLink(id: string, target: new (...args: any[]) => Bot | Server | User, shortLink: string) {
    const repository = this.source.getRepository(target)

    const short = await repository.findOne({ where: { shortLink } })

    if (!short) return shortLink
    if (short.id === id) return shortLink

    throw new NotFoundException({ code: ErrorCodes.ShortLinkTaken })
  }

  async validateTurnstile(secret: string, token: string, ip: string): Promise<{ success: boolean }> {
    const data = new URLSearchParams()
    data.append('secret', secret)
    data.append('response', token)
    data.append('remoteip', ip)

    const response = await fetch(cloudflareChallenges, {
      method: 'POST',
      body: data,
    }).catch(() => {
      throw new InternalServerErrorException({ code: ErrorCodes.TurnstileError })
    })

    return response.json()
      .catch(() => {
        throw new InternalServerErrorException({ code: ErrorCodes.TurnstileError })
      })
  }
}
